package com.xsy.camera2.opengl

import android.content.Context
import android.graphics.SurfaceTexture
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.Matrix
import android.os.Handler
import android.os.Message
import android.util.AttributeSet
import android.util.Log
import android.util.Size
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class MyGLSurfaceView2(context: Context, attributeSet: AttributeSet) :
    GLSurfaceView(context, attributeSet) {
    private var render: MyGLRender2

    init {
        setEGLContextClientVersion(3)
        val fragmentShaderCode = FileUtils.getAsset(context, TextureRender.fragment_file_path)
        val vertexShaderCode = FileUtils.getAsset(context, TextureRender.vertex_file_path)

        render = MyGLRender2(this, vertexShaderCode, fragmentShaderCode)
        setRenderer(render)

    }

    fun onDestroy() {
        render.onDestroy()
    }

    fun getRender(): MyGLRender2 {
        return render
    }
}

class MyGLRender2(
    glView: MyGLSurfaceView2,
    private val vertexShaderCode: String,
    private val fragmentShaderCode: String
) :
    GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
    private lateinit var textureRender: TextureRender
    private var mGLView = glView
    private var mSurfaceViewWidth = 0
    private var mSurfaceViewHeight = 0
    private var mHandler: Handler? = null
    private var mSurfaceTexture: SurfaceTexture? = null

    private var mMM = FloatArray(16)
    private var mMV = FloatArray(16)
    private var mProjM = FloatArray(16)
    private var mViewM = FloatArray(16)
    private var mMVP = FloatArray(16)

    private var mDegree = 0
    private var mScreenState = -1

    private var mIWidth = 0
    private var mIHeight = 0

    private var mOldIWidth = 0
    private var mOldIHeight = 0

    init{
        Matrix.setIdentityM(mMM, 0)
    }

    fun setHandler(handler: Handler?) {
        if (handler != null) {
            mHandler = handler
        }
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(1.0f, 0.0f, 0.0f, 1.0f)

        textureRender = TextureRender(vertexShaderCode, fragmentShaderCode)
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {

        mSurfaceViewWidth = width
        mSurfaceViewHeight = height
        mSurfaceTexture = SurfaceTexture(textureRender.getTextureId())
        mSurfaceTexture?.setOnFrameAvailableListener(this)
        val msg = Message.obtain()
        msg.obj = mSurfaceTexture
        msg.what = 1

        if (mHandler != null) {
            mHandler?.sendMessage(msg)
        }
        Log.d("MyGLSurfaceView", "width: $width")
        Log.d("MyGLSurfaceView", "height: $height")
        GLES30.glViewport(0, 0, width, height)
    }

    private  fun calculateViewport2() {
        val imageRatio = mIWidth / mIHeight.toFloat()
        val surfaceRatio = mSurfaceViewWidth/ mSurfaceViewHeight.toFloat()

        if(imageRatio > surfaceRatio) {
            val tb = imageRatio / surfaceRatio
            Matrix.orthoM(mProjM, 0, -1.0f, 1.0f, -tb, tb, -1.0f, 1.0f)
        }else if (imageRatio < surfaceRatio) {
            val lr = surfaceRatio / imageRatio
            Matrix.orthoM(mProjM, 0, -lr, lr, -1.0f, 1.0f, -1.0f, 1.0f)
        }else {
            Matrix.orthoM(mProjM, 0, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f)
        }

        Matrix.setLookAtM(mViewM, 0,
            0.0f , 0.0f, -1.0f,
            0.0f, 0.0f,0.0f,
            0.0f, 1.0f, 0.0f)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        calculateViewport2()
        Matrix.setRotateM(mMM, 0, mDegree.toFloat(), 0.0f, 0.0f, -1.0f)
        Matrix.multiplyMM(mMV, 0, mViewM, 0, mMM, 0)
        Matrix.multiplyMM(mMVP, 0,
            mProjM, 0,
            mMV, 0)
        mSurfaceTexture?.updateTexImage()
        textureRender.draw(mMVP)
    }

    fun onDestroy() {
        textureRender.onDestroy()
    }

    override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
        mGLView.requestRender()
    }

    fun setOrientation(degree: Int){
        if(mOldIWidth ==0 && mOldIHeight == 0) return

        mDegree = degree
        if(mDegree % 180 > 45 && mDegree % 180 < 135){
            if(mScreenState != 0) {
                mIWidth = mOldIHeight
                mIHeight = mOldIWidth
            }
//            Log.e("Renderer:", "$mIWidth, $mIHeight")
            mScreenState =0
        }else {
            mIWidth = mOldIWidth
            mIHeight = mOldIHeight
            mScreenState = 1
        }
    }

    fun setVideoSize(size: Size){
        mOldIWidth = size.width
        mOldIHeight = size.height
    }

}